<template>
  <div :id="id" ref="boxwrap" :class="className" :style="{height:height,width:width}" :title="title" :data="data" />
</template>

<script>
import 'echarts-gl'
import resize from '@/components/Charts/mixins/resize'

export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: 'chart'
    },
    id: {
      type: String,
      default: 'chart'
    },
    width: {
      type: String,
      default: '200px'
    },
    height: {
      type: String,
      default: '200px'
    },
    title: {
      type: String,
      default: ''
    },
    data: {
      type: Array,
      default: () => { return [] }
    }
  },
  data() {
    return {
      chart: null,
      fontColor: '#bebebe',
      // 蓝 红 灰
      itemColor: ['#dc69aa', '#ffb980', '#bf90d8', '#c9ab00', '#588dd5', '#e5cf0d', '#46a437', '#2ec7c9', '#f5994e', '#7289ab', '#6f5553'],
      total: 0
    }
  },
  watch: {
    data: {
      immediate: true,
      handler: function(newval, oldval) {
        this.data = newval
        if (this.chart) {
          this.chart.dispose()
          this.chart = null
          this.dealData()
        }
      },
      deep: true
    }
  },
  mounted() {
    this.domResize()
    this.dealData()
  },
  beforeDestroy() {
    if (!this.chart) {
      return
    }
    this.chart.dispose()
    this.chart = null
  },
  methods: {
    dealData() {
      this.data.forEach(val => {
        this.total += val.typeCount
      })
      this.initChart(this.data)
    },
    domResize() {
      const that = this
      const dom = this.$refs.boxwrap
      this.$erd.listenTo(dom, function(element) {
        that.chart.resize()
      })
    },
    // 生成扇形的曲面参数方程，用于 series-surface.parametricEquation
    getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
      // 计算
      const midRatio = (startRatio + endRatio) / 2

      const startRadian = startRatio * Math.PI * 2
      const endRadian = endRatio * Math.PI * 2
      const midRadian = midRatio * Math.PI * 2

      // 如果只有一个扇形，则不实现选中效果。
      if (startRatio === 0 && endRatio === 1) {
        isSelected = false
      }

      // 通过扇形内径/外径的值，换算出辅助参数 k（默认值 1/3）
      k = typeof k !== 'undefined' ? k : 1 / 3

      // 计算选中效果分别在 x 轴、y 轴方向上的位移（未选中，则位移均为 0）
      const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0
      const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0

      // 计算高亮效果的放大比例（未高亮，则比例为 1）
      const hoverRate = isHovered ? 1.05 : 1

      // 返回曲面参数方程
      return {
        u: {
          min: -Math.PI,
          max: Math.PI * 3,
          step: Math.PI / 32
        },
        v: {
          min: 0,
          max: Math.PI * 2,
          step: Math.PI / 20
        },
        x: function(u, v) {
          if (u < startRadian) {
            return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate
          }
          if (u > endRadian) {
            return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate
          }
          return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate
        },
        y: function(u, v) {
          if (u < startRadian) {
            return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate
          }
          if (u > endRadian) {
            return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate
          }
          return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate
        },
        z: function(u, v) {
          if (u < -Math.PI * 0.5) {
            return Math.sin(u)
          }
          if (u > Math.PI * 2.5) {
            return Math.sin(u) * h * 0.1
          }
          return Math.sin(v) > 0 ? 1 * h * 0.1 : -1
        }
      }
    },
    // 生成模拟 3D 饼图的配置项
    getPieOption3D(pieData, internalDiameterRatio) {
      const series = []
      let sumValue = 0
      let startValue = 0
      let endValue = 0
      const legendData = []
      const tooltipData = {}
      const k = typeof internalDiameterRatio !== 'undefined' ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio) : 1 / 3

      // 为每一个饼图数据，生成一个 series-surface 配置
      for (let i = 0; i < pieData.length; i++) {
        sumValue += pieData[i].value
        const seriesItem = {
          name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
          type: 'surface',
          parametric: true,
          wireframe: {
            show: false
          },
          pieData: pieData[i],
          pieStatus: {
            selected: false,
            hovered: false,
            k: k
          }
        }

        if (typeof pieData[i].itemStyle !== 'undefined') {
          const itemStyle = {}
          typeof pieData[i].itemStyle.color !== 'undefined' ? itemStyle.color = pieData[i].itemStyle.color : null
          typeof pieData[i].itemStyle.opacity !== 'undefined' ? itemStyle.opacity = pieData[i].itemStyle.opacity : null

          seriesItem.itemStyle = itemStyle
        }
        series.push(seriesItem)
      }

      // 使用上一次遍历时，计算出的数据和 sumValue，调用 getParametricEquation 函数，
      // 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation，也就是实现每一个扇形。
      for (let i = 0; i < series.length; i++) {
        endValue = startValue + series[i].pieData.value
        series[i].pieData.startRatio = startValue / sumValue
        series[i].pieData.endRatio = endValue / sumValue
        series[i].parametricEquation = this.getParametricEquation(series[i].pieData.startRatio, series[i].pieData.endRatio, false, false, k, series[i].pieData.value)
        startValue = endValue
        legendData.push(series[i].name)
        tooltipData[series[i].name] = (series[i].pieData.value / this.total * 100).toFixed(1)
      }

      // 补充一个透明的圆环，用于支撑高亮功能的近似实现。
      series.push({
        name: 'mouseoutSeries',
        type: 'surface',
        datavalue: pieData,
        parametric: true,
        wireframe: {
          show: false
        },
        itemStyle: {
          opacity: 0
        },
        parametricEquation: {
          u: {
            min: 0,
            max: Math.PI * 2,
            step: Math.PI / 20
          },
          v: {
            min: 0,
            max: Math.PI,
            step: Math.PI / 20
          },
          x: function(u, v) {
            return Math.sin(v) * Math.sin(u) + Math.sin(u)
          },
          y: function(u, v) {
            return Math.sin(v) * Math.cos(u) + Math.cos(u)
          },
          z: function(u, v) {
            return Math.cos(v) > 0 ? 0.1 : -0.1
          }
        }
      })

      // 准备待返回的配置项，把准备好的 legendData、series 传入。
      const option = {
        title: [{
          text: this.title + '报警等级贡献度',
          top: 10,
          left: 'center',
          textStyle: {
            fontSize: 16,
            color: this.fontColor,
            fontWeight: 'normal'
          }
        }],
        tooltip: {
          formatter: function(name) {
            let str = ''
            for (const k in tooltipData) {
              str += '<div>' + k + ':' + tooltipData[k] + '%</div>'
            }
            return str
          }
        },
        legend: {
          type: 'scroll',
          data: legendData,
          top: '15%',
          textStyle: {
            color: this.fontColor
          },
          pageIconColor: this.fontColor,
          pageTextStyle: {
            'color': this.fontColor
          }
        },
        xAxis3D: {
          min: -1,
          max: 1
        },
        yAxis3D: {
          min: -1,
          max: 1
        },
        zAxis3D: {
          min: -1,
          max: 1
        },
        grid3D: {
          show: false,
          boxHeight: 20,
          bottom: 0,
          viewControl: { // 3d效果可以放大、旋转等，参考官方配置
            alpha: 45, // 角度
            distance: 360, // 视角距离--表现为大小
            rotateSensitivity: 0,
            zoomSensitivity: 0,
            panSensitivity: 0,
            autoRotate: false
          }
        },
        series: series
      }
      return option
    },
    initChart(data) {
      const dataArr = []
      data.forEach((val, idx) => {
        dataArr.push({
          name: val.name,
          value: val.typeCount,
          itemStyle: {
            opacity: 1,
            color: this.itemColor[idx]
          }
        })
      })
      // console.log('dataArr', dataArr)
      this.chart = this.$echarts.init(document.getElementById(this.id))
      this.chart.setOption(this.getPieOption3D(dataArr, 0.5))
    }
  }
}
</script>
